﻿using AutoMapper;
using CK.Sprite.Cache;
using CK.Sprite.Framework;
using JetBrains.Annotations;
using Microsoft.Extensions.Options;
using MySqlX.XDevAPI.Common;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace CK.Sprite.Form.Core
{
    public class SpriteViewLocalCache : LocalCache<SpriteViewVueDto>
    {
        public override string CacheKey => CommonConsts.SpriteViewCacheKey;

        public override Dictionary<Guid, SpriteViewVueDto> GetAllDict(string applicationCode)
        {
            if (!LocalCacheContainer.IsEnabledLocalCache)
            {
                return _serviceProvider.DoDapperService(DefaultDbConfig, (unitOfWork) =>
                {
                    return GetSpriteViewVueDtos(applicationCode, unitOfWork);
                });
            }
            else
            {
                return (Dictionary<Guid, SpriteViewVueDto>)LocalCacheContainer.Get($"{CommonConsts.SpriteFormCachePreKey}-{applicationCode}_{CacheKey}", key =>
                {
                    return _serviceProvider.DoDapperService(DefaultDbConfig, (unitOfWork) =>
                    {
                        return GetSpriteViewVueDtos(applicationCode, unitOfWork);
                    });
                });
            }
        }

        private Dictionary<Guid, SpriteViewVueDto> GetSpriteViewVueDtos(string applicationCode, IUnitOfWork unitOfWork)
        {
            var spriteViewRepository = ConnectionFactory.GetConnectionProvider(DefaultDbConfig.ConnectionType).GetRepository<ISpriteViewRepository>(unitOfWork);
            var spriteViews = spriteViewRepository.GetAllSpriteViewByApplicationCode(applicationCode);

            var results = new Dictionary<Guid, SpriteViewVueDto>();
            foreach (var spriteView in spriteViews)
            {
                var spriteViewVueDto = new SpriteViewVueDto()
                {
                    Id = spriteView.Id,
                    ApplicationCode = spriteView.ApplicationCode,
                    Name = spriteView.Name,
                    Version = spriteView.Version,
                    ViewType = spriteView.ViewType,
                    PropertySettings = string.IsNullOrEmpty(spriteView.PropertySettings) ? null : JsonConvert.DeserializeObject(spriteView.PropertySettings),
                    Controls = string.IsNullOrEmpty(spriteView.Controls) ? null : JsonConvert.DeserializeObject(spriteView.Controls),
                    WrapInfos = string.IsNullOrEmpty(spriteView.WrapInfos) ? null : JsonConvert.DeserializeObject(spriteView.WrapInfos),
                    Extension1s = string.IsNullOrEmpty(spriteView.Extension1s) ? null : JsonConvert.DeserializeObject(spriteView.Extension1s),
                    Extension2s = string.IsNullOrEmpty(spriteView.Extension2s) ? null : JsonConvert.DeserializeObject(spriteView.Extension2s),
                };

                spriteViewVueDto.Rules = SpriteLocalCacheHelper.MakeRules(spriteView.Rules);

                var relasionInfos = new List<RelasionInfo>();
                SpriteLocalCacheHelper.MakeWrapInfos(spriteViewVueDto.WrapInfos, relasionInfos);
                SpriteLocalCacheHelper.MakeControls(spriteViewVueDto.Controls);

                if ((spriteViewVueDto.ViewType == EViewType.ItemView || spriteViewVueDto.ViewType == EViewType.ViewPanel) && spriteViewVueDto.Extension1s != null)
                {
                    foreach (var itemViewRow in (spriteViewVueDto.Extension1s as JArray))
                    {
                        SpriteLocalCacheHelper.ChangeStringToObject(itemViewRow, "propertySettings");
                        foreach (var itemViewCol in (itemViewRow["children"] as JArray))
                        {
                            SpriteLocalCacheHelper.ChangeStringToObject(itemViewCol, "propertySettings");
                            SpriteLocalCacheHelper.ChangeStringToObject(itemViewCol, "labelSettings");
                            SpriteLocalCacheHelper.ChangeStringToObject(itemViewCol, "controlSettings");
                            SpriteLocalCacheHelper.ChangeStringToObject(itemViewCol, "express");
                            SpriteLocalCacheHelper.ChangeStringToObject(itemViewCol, "wrapConfigs");
                            SpriteLocalCacheHelper.ChangeStringToObject(itemViewCol, "validateRuleJson");
                            if (itemViewCol["colType"].ToString() == "2")
                            {
                                AddRelationInfos(relasionInfos, Guid.Parse(itemViewCol["objId"].ToString()), 2);
                            }

                            if (itemViewCol["colType"].ToString() == "3")
                            {
                                AddRelationInfos(relasionInfos, Guid.Parse(itemViewCol["objId"].ToString()), 1);
                            }
                        }
                    }
                }

                if ((spriteViewVueDto.ViewType == EViewType.ListView || spriteViewVueDto.ViewType == EViewType.ListLocalView) && spriteViewVueDto.Extension1s != null)
                {
                    foreach (var listViewFilter in (spriteViewVueDto.Extension1s as JArray))
                    {
                        SpriteLocalCacheHelper.ChangeStringToObject(listViewFilter, "labelPropertySettings");
                        SpriteLocalCacheHelper.ChangeStringToObject(listViewFilter, "controlSettings");
                    }
                }

                if ((spriteViewVueDto.ViewType == EViewType.ListView || spriteViewVueDto.ViewType == EViewType.ListLocalView) && spriteViewVueDto.Extension2s != null)
                {
                    foreach (var listCustomerColumn in (spriteViewVueDto.Extension2s as JArray))
                    {
                        SpriteLocalCacheHelper.ChangeStringToObject(listCustomerColumn, "editSettings");
                        SpriteLocalCacheHelper.ChangeStringToObject(listCustomerColumn, "controlSettings");
                    }
                }

                spriteViewVueDto.RelationInfos = relasionInfos;

                results.Add(spriteViewVueDto.Id, spriteViewVueDto);
            }

            return results;
        }

        private void AddRelationInfos(List<RelasionInfo> relasionInfos, Guid id, int relationType)
        {
            if (!relasionInfos.Any(r => r.Id == id))
            {
                relasionInfos.Add(new RelasionInfo()
                {
                    Id = id,
                    RelationType = relationType
                });
            }
        }
    }
}
